Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalidate variables cache in SetVariableAsync and in EvaluateExpressionAsync to have actual variables data #2169

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

Fantoom
Copy link

@Fantoom Fantoom commented Jul 31, 2024

PR Summary

If the user modifies, adds, or removes a variable (e.g., with SetVariable or Evaluate request) and then sends Variables request (which calls GetVariables), they get unmodified variables set from the cached variables field.

I have added FetchStackFramesAndVariablesAsync calls in SetVariableAsync and in EvaluateExpressionAsync to invalidate the cache and get actual data on Variables request

This is probably related to #58, but I am not sure.

PR Context

We are working on adding debugger support to https://github.com/ant-druha/intellij-powershell

Fantoom added a commit to Fantoom/intellij-powershell that referenced this pull request Aug 1, 2024
@Fantoom
Copy link
Author

Fantoom commented Aug 1, 2024

@andyleejordan Can you please review this one?

Fantoom added a commit to Fantoom/intellij-powershell that referenced this pull request Aug 2, 2024
Fantoom added a commit to Fantoom/intellij-powershell that referenced this pull request Aug 2, 2024
Fantoom added a commit to Fantoom/intellij-powershell that referenced this pull request Aug 2, 2024
Add Variables cache
see PowerShell/PowerShellEditorServices#2169

Debugger WIP 15
Catch value modification errors

Debugger WIP 15
Debugger eval completion

Debugger WIP 14
Add id to document

Debugger WIP 13
Remove useless files

Debugger WIP 12
Add Variable Test

Debugger WIP 11.2
Remove useless comments

Debugger WIP 11.1
Change hardcoded parameter to variable
remove unused variable from EvaluationTest.testEvaluation

Debugger WIP 11
Call clientSession.terminateDebugging() on dispose
Change PowerShellDebuggerVariableValue supertype to XNamedValue
update formatting
Test:
Update BreakpointTest
Add EvaluationTest
Add StepTest

Debugger WIP 10
Add tests
Add BreakpointTest

Debugger WIP 9
Set variable value

Debugger WIP 8
run project file instead hardcoded file
set all breakpoints on start

Debugger WIP 7
Step Over/In/Out support
Terminate support

Debugger WIP 6
Conditional and log support

Debugger WIP 5
IDE Breakpoints support
Resume (continue) support

Debugger WIP 5
Variable list Complex objects

Debugger WIP 3
variable list
eval

Debugger WIP 2

Debugger WIP
Fantoom added a commit to Fantoom/intellij-powershell that referenced this pull request Aug 2, 2024
Add Variables cache
see PowerShell/PowerShellEditorServices#2169

Debugger WIP 15
Catch value modification errors

Debugger WIP 15
Debugger eval completion

Debugger WIP 14
Add id to document

Debugger WIP 13
Remove useless files

Debugger WIP 12
Add Variable Test

Debugger WIP 11.2
Remove useless comments

Debugger WIP 11.1
Change hardcoded parameter to variable
remove unused variable from EvaluationTest.testEvaluation

Debugger WIP 11
Call clientSession.terminateDebugging() on dispose
Change PowerShellDebuggerVariableValue supertype to XNamedValue
update formatting
Test:
Update BreakpointTest
Add EvaluationTest
Add StepTest

Debugger WIP 10
Add tests
Add BreakpointTest

Debugger WIP 9
Set variable value

Debugger WIP 8
run project file instead hardcoded file
set all breakpoints on start

Debugger WIP 7
Step Over/In/Out support
Terminate support

Debugger WIP 6
Conditional and log support

Debugger WIP 5
IDE Breakpoints support
Resume (continue) support

Debugger WIP 5
Variable list Complex objects

Debugger WIP 3
variable list
eval

Debugger WIP 2

Debugger WIP
Copy link
Member

@andyleejordan andyleejordan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yes, we looked at this in triage and I liked it. I added to my list for next release but I can at least merge sooner than that. I wanted to double-check FetchStackFramesAndVariablesAsync (just did) and while I agree it's related to #58 I don't think it'll solve it, but I think the solution for that is doing the same thing except after excecution of a user command in the debugger prompt. So, very similarly fixable. Thanks so much!

@andyleejordan
Copy link
Member

@Fantoom do you think the CI failure is related to #2170?

@ForNeVeR
Copy link
Contributor

ForNeVeR commented Aug 3, 2024

Looks like the same issue. I have a hypothesis (not yet checked with the sources): what if a test executes some operation that would cause that exception, but it is currently masked by the fact that PSES doesn't re-evaluate the variables after each step?

In that case, it is possible that there's a real error that is hidden from the test.

@Fantoom
Copy link
Author

Fantoom commented Aug 5, 2024

@andyleejordan

@Fantoom do you think the CI failure is related to #2170?

I have debugged it and have found that after SetVariable, FetchStackFramesAndVariablesAsync fetches variables with two more variables called "$__psEditorServices_CallStack." And that changes the referenceIds of the scopes.

I see two ways of solving this:

  1. Users should clear their own cache after SetValue/Evaluate and refetch with GetVariables. I'm not sure if this violates the DAP or not
  2. Update variable value in the cache instead of refetching it. I am not sure if this reflects all the changes or not

@ForNeVeR
Copy link
Contributor

ForNeVeR commented Aug 5, 2024

After a bit of additional digging (disclaimer: I am a supervisor of @Fantoom), we found these lines in the DAP spec:

Some complex structural objects such as scopes or variables are not returned directly with their containers (stack frames, scopes, variables), but must be retrieved with separate scopes and variables requests based on object references. An object reference is an integer in the open interval (0, 231) assigned to objects by the debug adapter.

To simplify the management of object references in debug adapters, their lifetime is limited to the current suspended state. Once execution resumes, object references become invalid and DAP clients must not use them. When execution is paused again, object references no longer refer to the same objects. This means that a debug adapter can easily use sequentially assigned integers for different objects and reset the counter to 1 when execution resumes.

Variable references not related to the current suspended state, such as those from evaluate requests or in output events, should be preserved as long as feasible for the debug adapter so that the client may later inspect them.

Please note that other object references like threadId do not have limited lifetime because that would prevent something like the pause request from working in the running state.

I am not very sure, but to me it looks like, unfortunately, this PR breaks the spec expectation that the variable ids are preserved between the suspend points (and effectively introduces a new suspend state after any variable evaluation).

I'd rely on your judgement, folks, on what to do with that further. We might have to redesign this part, to allow some kind of partial update of the suspend state, preserving the variable ids?

ForNeVeR pushed a commit to Fantoom/intellij-powershell that referenced this pull request Aug 16, 2024
Add Variables cache
see PowerShell/PowerShellEditorServices#2169

Debugger WIP 15
Catch value modification errors

Debugger WIP 15
Debugger eval completion

Debugger WIP 14
Add id to document

Debugger WIP 13
Remove useless files

Debugger WIP 12
Add Variable Test

Debugger WIP 11.2
Remove useless comments

Debugger WIP 11.1
Change hardcoded parameter to variable
remove unused variable from EvaluationTest.testEvaluation

Debugger WIP 11
Call clientSession.terminateDebugging() on dispose
Change PowerShellDebuggerVariableValue supertype to XNamedValue
update formatting
Test:
Update BreakpointTest
Add EvaluationTest
Add StepTest

Debugger WIP 10
Add tests
Add BreakpointTest

Debugger WIP 9
Set variable value

Debugger WIP 8
run project file instead hardcoded file
set all breakpoints on start

Debugger WIP 7
Step Over/In/Out support
Terminate support

Debugger WIP 6
Conditional and log support

Debugger WIP 5
IDE Breakpoints support
Resume (continue) support

Debugger WIP 5
Variable list Complex objects

Debugger WIP 3
variable list
eval

Debugger WIP 2

Debugger WIP
ForNeVeR pushed a commit to ant-druha/intellij-powershell that referenced this pull request Aug 20, 2024
Add Variables cache
see PowerShell/PowerShellEditorServices#2169

Debugger WIP 15
Catch value modification errors

Debugger WIP 15
Debugger eval completion

Debugger WIP 14
Add id to document

Debugger WIP 13
Remove useless files

Debugger WIP 12
Add Variable Test

Debugger WIP 11.2
Remove useless comments

Debugger WIP 11.1
Change hardcoded parameter to variable
remove unused variable from EvaluationTest.testEvaluation

Debugger WIP 11
Call clientSession.terminateDebugging() on dispose
Change PowerShellDebuggerVariableValue supertype to XNamedValue
update formatting
Test:
Update BreakpointTest
Add EvaluationTest
Add StepTest

Debugger WIP 10
Add tests
Add BreakpointTest

Debugger WIP 9
Set variable value

Debugger WIP 8
run project file instead hardcoded file
set all breakpoints on start

Debugger WIP 7
Step Over/In/Out support
Terminate support

Debugger WIP 6
Conditional and log support

Debugger WIP 5
IDE Breakpoints support
Resume (continue) support

Debugger WIP 5
Variable list Complex objects

Debugger WIP 3
variable list
eval

Debugger WIP 2

Debugger WIP
@andyleejordan
Copy link
Member

@ForNeVeR I have this on my radar, just getting back to work after breaking my hand! Will reply more in depth soon.

…Services.Services.DebugService.SetVariableAsync and in Microsoft.PowerShell.EditorServices.Services.DebugService.EvaluateExpressionAsync to invalidate variables cache and use actual variables data.
@JustinGrote
Copy link
Collaborator

Rebasing to re-run tests, should be OK now.

@andyleejordan
Copy link
Member

After a bit of additional digging (disclaimer: I am a supervisor of @Fantoom), we found these lines in the DAP spec:

Some complex structural objects such as scopes or variables are not returned directly with their containers (stack frames, scopes, variables), but must be retrieved with separate scopes and variables requests based on object references. An object reference is an integer in the open interval (0, 231) assigned to objects by the debug adapter.
To simplify the management of object references in debug adapters, their lifetime is limited to the current suspended state. Once execution resumes, object references become invalid and DAP clients must not use them. When execution is paused again, object references no longer refer to the same objects. This means that a debug adapter can easily use sequentially assigned integers for different objects and reset the counter to 1 when execution resumes.
Variable references not related to the current suspended state, such as those from evaluate requests or in output events, should be preserved as long as feasible for the debug adapter so that the client may later inspect them.
Please note that other object references like threadId do not have limited lifetime because that would prevent something like the pause request from working in the running state.

I am not very sure, but to me it looks like, unfortunately, this PR breaks the spec expectation that the variable ids are preserved between the suspend points (and effectively introduces a new suspend state after any variable evaluation).

I'd rely on your judgement, folks, on what to do with that further. We might have to redesign this part, to allow some kind of partial update of the suspend state, preserving the variable ids?

@JustinGrote don't forget this part!

@JustinGrote
Copy link
Collaborator

Sorry, I meant to say the test should be fine, not that the pr is ready to be merged

@andyleejordan andyleejordan force-pushed the main branch 2 times, most recently from 80b2351 to 9ce8911 Compare November 18, 2024 19:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants